﻿using System.Linq;
using MCP.BL;
using MCP.BL.Messages;
using MCP.Data.CF_Entities;
using MCP.Model.Helpers;
using MCP.Model.Repositories.Interfaces;
using System;

namespace MCP.Model.Repositories.CF
{
    public class AccountRepository : IAccountRepository
    {
        private readonly MCPContext context;
        private readonly IUnitOfWork unitOfWork;

        public AccountRepository(IUnitOfWork unit, MCPContext context)
        {
            this.context = context;
            this.unitOfWork = unit;
        }

        public OperationResult<User> GetUser(string username)
        {
            if (string.IsNullOrEmpty(username)) return null;

            OperationResult<User> result;

            try
            {
                var user = this.context.Users.ToList().SingleOrDefault(u => u.Username == username);
                result = new OperationResult<User>(user);
            }
            catch (Exception exc)
            {
                result = new OperationResult<User>(exc);
            }
            
            return result;
        }

        public OperationResult<User> GetUser(int userID)
        {
            if (userID == 0) return null;

            OperationResult<User> result;

            try
            {
                var user = this.context.Users.SingleOrDefault(u => u.ID == userID);
                result = new OperationResult<User>(user);
            }
            catch (Exception exc)
            {
                result = new OperationResult<User>(exc);
            }

            return result;
        }

        public OperationResult<Settings> GetUserSettings()
        {
            OperationResult<Settings> result;

            try
            {
                var settings = this.context.Users.SingleOrDefault(u => u.ID == CurrentUserHelper.UserID).Settings;
                result = new OperationResult<Settings>(settings);
            }
            catch (Exception exc)
            {
                result = new OperationResult<Settings>(exc);
            }

            return result;
        }
        
        public CurrentBalanceMessage GetCurrentBalanceMessage()
        {
            var message = new CurrentBalanceMessage();

			if (CurrentUserHelper.User.MonthIncome.HasValue)
			{
				// DB connection:
				double? currentBalance = null;
				double? percent = null;
				var getChecksResult = this.unitOfWork.CheckRepository.GetChecks();
				
                if (getChecksResult.Success)
				{
				    var monthSpends = (double)getChecksResult.Result
                        .Where(c => c.Date.Month == DateTime.Now.Month)
                        .Sum(c => c.TotalPrice);
				    currentBalance = CurrentUserHelper.User.MonthIncome - monthSpends - CurrentUserHelper.User.MinBalance;

				    percent = currentBalance/(CurrentUserHelper.User.MonthIncome - CurrentUserHelper.User.MinBalance)*100;

                    message.ComposeMessage(currentBalance, percent);
				}
				else
				{
				    // TODO: resolve this situation!
				}
			}

			return message;
        }
		
        public OperationResult UpdateUserSettings(Settings settings)
        {
            if (settings == null) return null;

            OperationResult result;

            try
            {
                var currentUser = this.context.Users.SingleOrDefault(u => u.ID == CurrentUserHelper.UserID);
                if (currentUser == null)
                {
                    result = new OperationResult(false, new ErrorMessage("Unable to find current user in DB."));
                }
                else
                {
                    currentUser.Settings = settings;
                    this.context.SaveChanges();

                    result = new OperationResult(true);
                }
            }
            catch (Exception exc)
            {
                result = new OperationResult(exc);
            }

            return result;
        }
		
        public OperationResult<Settings> GetCurrentUserSettings()
        {
            OperationResult<Settings> result;

            try
            {
                var currentUser = this.context.Users.SingleOrDefault(u => u.ID == CurrentUserHelper.UserID);
                if (currentUser == null)
                {
                    result = new OperationResult<Settings>(new ErrorMessage("Unable to find current user in DB."));
                }
                else
                {
                    result = new OperationResult<Settings>(currentUser.Settings);
                }
            }
            catch (Exception exc)
            {
                result = new OperationResult<Settings>(exc);
            }

            return result;
        }

        /// <summary>
        /// Adds basic users for new DEV server instance.
        /// </summary>
        public void InitializeBaseUsers()
        {
            if (this.context.Users.SingleOrDefault(u => u.Username == "user") == null)
            {
                this.context.Users.Add(new User() { Username = "user", Password = "user", Settings = new Settings()});
            }

            if (this.context.Users.SingleOrDefault(u => u.Username == "admin") == null)
            {
				this.context.Users.Add(new User() { Username = "admin", Password = "admin", Settings = new Settings() });
            }

            this.context.SaveChanges();
        }
    }
}